package com.panfeng.xcloud.common.core.utils;

import org.springframework.util.ObjectUtils;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public abstract class StringUtils {

    private static final String FOLDER_SEPARATOR = "/";
    private static final String WINDOWS_FOLDER_SEPARATOR = "\\";
    private static final String TOP_PATH = "..";
    private static final String CURRENT_PATH = ".";
    private static final char EXTENSION_SEPARATOR = 46;

    public static String getRandomString(int length) {
        //定义字符
        StringBuffer buffer = new StringBuffer("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        return getRandomStr(length, buffer);
    }

    public static String getRandomNumber(int length) {
        //定义字符
        StringBuffer buffer = new StringBuffer("0123456789");
        return getRandomStr(length, buffer);
    }

    public static String getRandomNickName(int length) {
        //定义字符
        StringBuffer buffer = new StringBuffer("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
        return getRandomStr(length, buffer);
    }

    public static String getOrderIdByUUId(int machineId) {
        //最大支持1-9个集群机器部署
        int hashCodev = UUID.randomUUID().toString().hashCode();
        if (hashCodev < 0) {
            //有可能是负数
            hashCodev = -hashCodev;
        }
        //"%015d"的意思：0代表不足位数的补0，这样可以确保相同的位数，15是位数也就是要得到到的字符串长度是15，d代表数字。
        return machineId + String.format("%015d", hashCodev);
    }

    private static String getRandomStr(int length, StringBuffer buffer) {
        StringBuffer sb = new StringBuffer();
        Random r = new Random();
        int range = buffer.length();
        //循环字符长度
        for (int i = 0; i < length; i++) {
            //生成随机字符
            sb.append(buffer.charAt(r.nextInt(range)));
        }
        return sb.toString();
    }

    public static String stringToAscii(String value) {
        StringBuffer sbu = new StringBuffer();
        char[] chars = value.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            if (i != chars.length - 1) {
                sbu.append((int) chars[i]).append(",");
            } else {
                sbu.append((int) chars[i]);
            }
        }
        return sbu.toString();
    }

    public static String asciiToString(String value) {
        StringBuffer sbu = new StringBuffer();
        String[] chars = value.split(",");
        for (int i = 0; i < chars.length; i++) {
            sbu.append((char) Integer.parseInt(chars[i]));
        }
        return sbu.toString();
    }

    /**
     * 构建sql排序条件
     *
     * @param orderByClauseString
     * @return
     */
    public static String buidOrderClauseByParam(String orderByClauseString) {
        if (StringUtils.isEmpty(orderByClauseString)) {
            return "";
        }
        if (orderByClauseString.indexOf(",") != -1) {
            String[] orderByClauseArray = orderByClauseString.split(",");
            StringBuffer orderByClauseSb = new StringBuffer();
            for (int i = 0; i < orderByClauseArray.length; i++) {
                String orderItem = orderByClauseArray[i];
                String[] orderByArray = orderItem.split("_", 2);
                orderByClauseSb.append(orderByArray[0]).append(" ").append(orderByArray[1]).append(",");
            }
            if (orderByClauseSb.length() > 0) {
                //删除最后一个
                orderByClauseSb.deleteCharAt(orderByClauseSb.length() - 1);
            }
            return orderByClauseSb.toString();
        } else {
            String[] orderByArray = orderByClauseString.split("_", 2);
            return orderByArray[0] + " " + orderByArray[1];
        }
    }

    /**
     * 使用给定的 charset 将此 String 编码到 byte 序列，并将结果存储到新的 byte 数组。
     *
     * @param content 字符串对象
     * @param charset 编码方式
     * @return 所得 byte 数组
     */
    public static byte[] getContentBytes(String content, String charset) {
        if (charset == null || "".equals(charset)) {
            return content.getBytes();
        }
        try {
            return content.getBytes(charset);
        } catch (UnsupportedEncodingException ex) {
            throw new IllegalArgumentException("Not support:" + charset, ex);
        }
    }

    /**
     * 压缩
     *
     * @param oldString
     * @param charSet
     * @return
     */
    public static String compress(String oldString, String charSet) {
        if (oldString == null || oldString.length() == 0) {
            return oldString;
        }
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            GZIPOutputStream gzip = new GZIPOutputStream(out);
            gzip.write(oldString.getBytes());
            gzip.close();
            /**
             * TODO:toString()使用平台默认编码，也可以显式的指定如toString("GBK")
             */
            return out.toString(charSet);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 解压缩
     *
     * @param oldString
     * @param charSet
     * @return
     */
    public static String unCompress(String oldString, String charSet) {
        if (oldString == null || oldString.length() == 0) {
            return oldString;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ByteArrayInputStream in = new ByteArrayInputStream(oldString.getBytes(charSet));
            GZIPInputStream gunzip = new GZIPInputStream(in);
            byte[] buffer = new byte[256];
            int n;
            while ((n = gunzip.read(buffer)) >= 0) {
                out.write(buffer, 0, n);
            }
            /**
             * TODO:toString()使用平台默认编码，也可以显式的指定如toString("GBK")
             */
            return out.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    public static String unicode2String(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");
        string.append(hex[0]);
        for (int i = 1; i < hex.length; i++) {
            // 转换出每一个代码点
            int data = Integer.parseInt(hex[i].substring(0, 4), 16);

            // 追加成string
            string.append((char) data + hex[i].substring(4));
        }
        return string.toString();
    }

    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        return isNum.matches();
    }

    public static boolean hasLength(CharSequence str) {
        return ((str != null) && (str.length() > 0));
    }

    public static boolean hasLength(String str) {
        return hasLength(str);
    }

    public static boolean hasText(CharSequence str) {
        if (!(hasLength(str))) {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; ++i) {
            if (!(Character.isWhitespace(str.charAt(i)))) {
                return true;
            }
        }
        return false;
    }

    public static boolean hasText(String str) {
        return hasText(str);
    }

    public static boolean containsWhitespace(CharSequence str) {
        if (!(hasLength(str))) {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; ++i) {
            if (Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    public static boolean containsWhitespace(String str) {
        return containsWhitespace(str);
    }

    public static String trimWhitespace(String str) {
        if (!(hasLength(str))) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while ((buf.length() > 0) && (Character.isWhitespace(buf.charAt(0)))) {
            buf.deleteCharAt(0);
        }
        while ((buf.length() > 0)
                && (Character.isWhitespace(buf.charAt(buf.length() - 1)))) {
            buf.deleteCharAt(buf.length() - 1);
        }
        return buf.toString();
    }

    public static String trimAllWhitespace(String str) {
        if (!(hasLength(str))) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        int index = 0;
        while (buf.length() > index) {
            if (Character.isWhitespace(buf.charAt(index))) {
                buf.deleteCharAt(index);
            }

            ++index;
        }

        return buf.toString();
    }

    public static String trimLeadingWhitespace(String str) {
        if (!(hasLength(str))) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while ((buf.length() > 0) && (Character.isWhitespace(buf.charAt(0)))) {
            buf.deleteCharAt(0);
        }
        return buf.toString();
    }

    public static String trimTrailingWhitespace(String str) {
        if (!(hasLength(str))) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while ((buf.length() > 0)
                && (Character.isWhitespace(buf.charAt(buf.length() - 1)))) {
            buf.deleteCharAt(buf.length() - 1);
        }
        return buf.toString();
    }

    public static String trimLeadingCharacter(String str, char leadingCharacter) {
        if (!(hasLength(str))) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while ((buf.length() > 0) && (buf.charAt(0) == leadingCharacter)) {
            buf.deleteCharAt(0);
        }
        return buf.toString();
    }

    public static String trimTrailingCharacter(String str,
                                               char trailingCharacter) {
        if (!(hasLength(str))) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str);
        while ((buf.length() > 0)
                && (buf.charAt(buf.length() - 1) == trailingCharacter)) {
            buf.deleteCharAt(buf.length() - 1);
        }
        return buf.toString();
    }

    public static boolean startsWithIgnoreCase(String str, String prefix) {
        if ((str == null) || (prefix == null)) {
            return false;
        }
        if (str.startsWith(prefix)) {
            return true;
        }
        if (str.length() < prefix.length()) {
            return false;
        }
        String lcStr = str.substring(0, prefix.length()).toLowerCase();
        String lcPrefix = prefix.toLowerCase();
        return lcStr.equals(lcPrefix);
    }

    public static boolean endsWithIgnoreCase(String str, String suffix) {
        if ((str == null) || (suffix == null)) {
            return false;
        }
        if (str.endsWith(suffix)) {
            return true;
        }
        if (str.length() < suffix.length()) {
            return false;
        }

        String lcStr = str.substring(str.length() - suffix.length())
                .toLowerCase();
        String lcSuffix = suffix.toLowerCase();
        return lcStr.equals(lcSuffix);
    }

    public static boolean substringMatch(CharSequence str, int index,
                                         CharSequence substring) {
        for (int j = 0; j < substring.length(); ++j) {
            int i = index + j;
            if ((i >= str.length()) || (str.charAt(i) != substring.charAt(j))) {
                return false;
            }
        }
        return true;
    }

    public static int countOccurrencesOf(String str, String sub) {
        if ((str == null) || (sub == null) || (str.length() == 0)
                || (sub.length() == 0)) {
            return 0;
        }
        int count = 0;
        int pos = 0;
        int idx = 0;
        while ((idx = str.indexOf(sub, pos)) != -1) {
            ++count;
            pos = idx + sub.length();
        }
        return count;
    }

    public static String replace(String inString, String oldPattern,
                                 String newPattern) {
        if ((!(hasLength(inString))) || (!(hasLength(oldPattern)))
                || (newPattern == null)) {
            return inString;
        }
        StringBuffer sbuf = new StringBuffer();

        int pos = 0;
        int index = inString.indexOf(oldPattern);

        int patLen = oldPattern.length();
        while (index >= 0) {
            sbuf.append(inString, pos, index);
            sbuf.append(newPattern);
            pos = index + patLen;
            index = inString.indexOf(oldPattern, pos);
        }
        sbuf.append(inString.substring(pos));

        return sbuf.toString();
    }

    public static String delete(String inString, String pattern) {
        return replace(inString, pattern, "");
    }

    public static String deleteAny(String inString, String charsToDelete) {
        if ((!(hasLength(inString))) || (!(hasLength(charsToDelete)))) {
            return inString;
        }
        StringBuffer out = new StringBuffer();
        for (int i = 0; i < inString.length(); ++i) {
            char c = inString.charAt(i);
            if (charsToDelete.indexOf(c) == -1) {
                out.append(c);
            }
        }
        return out.toString();
    }

    public static String quote(String str) {
        return ((str != null) ? "'" + str + "'" : null);
    }

    public static Object quoteIfString(Object obj) {
        return ((obj instanceof String) ? quote((String) obj) : obj);
    }

    public static String unqualify(String qualifiedName) {
        return unqualify(qualifiedName, '.');
    }

    public static String unqualify(String qualifiedName, char separator) {
        return qualifiedName
                .substring(qualifiedName.lastIndexOf(separator) + 1);
    }

    public static String capitalize(String str) {
        return changeFirstCharacterCase(str, true);
    }

    public static String uncapitalize(String str) {
        return changeFirstCharacterCase(str, false);
    }

    private static String changeFirstCharacterCase(String str,
                                                   boolean capitalize) {
        if ((str == null) || (str.length() == 0)) {
            return str;
        }
        StringBuffer buf = new StringBuffer(str.length());
        if (capitalize) {
            buf.append(Character.toUpperCase(str.charAt(0)));
        } else {
            buf.append(Character.toLowerCase(str.charAt(0)));
        }
        buf.append(str.substring(1));
        return buf.toString();
    }

    public static String getFilename(String path) {
        if (path == null) {
            return null;
        }
        int separatorIndex = path.lastIndexOf("/");
        return ((separatorIndex != -1) ? path.substring(separatorIndex + 1)
                : path);
    }

    public static String getFilenameExtension(String path) {
        if (path == null) {
            return null;
        }
        int sepIndex = path.lastIndexOf(46);
        return ((sepIndex != -1) ? path.substring(sepIndex + 1) : null);
    }

    public static String stripFilenameExtension(String path) {
        if (path == null) {
            return null;
        }
        int sepIndex = path.lastIndexOf(46);
        return ((sepIndex != -1) ? path.substring(0, sepIndex) : path);
    }

    public static String applyRelativePath(String path, String relativePath) {
        int separatorIndex = path.lastIndexOf("/");
        if (separatorIndex != -1) {
            String newPath = path.substring(0, separatorIndex);
            if (!(relativePath.startsWith("/"))) {
                newPath = newPath + "/";
            }
            return newPath + relativePath;
        }

        return relativePath;
    }

    public static String cleanPath(String path) {
        if (path == null) {
            return null;
        }
        String pathToUse = replace(path, "\\", "/");

        int prefixIndex = pathToUse.indexOf(":");
        String prefix = "";
        if (prefixIndex != -1) {
            prefix = pathToUse.substring(0, prefixIndex + 1);
            pathToUse = pathToUse.substring(prefixIndex + 1);
        }
        if (pathToUse.startsWith("/")) {
            prefix = prefix + "/";
            pathToUse = pathToUse.substring(1);
        }

        String[] pathArray = delimitedListToStringArray(pathToUse, "/");
        List pathElements = new LinkedList();
        int tops = 0;

        for (int i = pathArray.length - 1; i >= 0; --i) {
            String element = pathArray[i];
            if (".".equals(element)) {
                continue;
            }
            if ("..".equals(element)) {
                ++tops;
            } else if (tops > 0) {
                --tops;
            } else {
                pathElements.add(0, element);
            }

        }

        for (int i = 0; i < tops; ++i) {
            pathElements.add(0, "..");
        }

        return prefix + collectionToDelimitedString(pathElements, "/");
    }

    public static boolean pathEquals(String path1, String path2) {
        return cleanPath(path1).equals(cleanPath(path2));
    }

    public static Locale parseLocaleString(String localeString) {
        String[] parts = tokenizeToStringArray(localeString, "_ ", false, false);
        String language = (parts.length > 0) ? parts[0] : "";
        String country = (parts.length > 1) ? parts[1] : "";
        String variant = "";
        if (parts.length >= 2) {
            int endIndexOfCountryCode = localeString.indexOf(country)
                    + country.length();

            variant = trimLeadingWhitespace(localeString
                    .substring(endIndexOfCountryCode));
            if (variant.startsWith("_")) {
                variant = trimLeadingCharacter(variant, '_');
            }
        }
        return ((language.length() > 0) ? new Locale(language, country, variant)
                : null);
    }

    public static String toLanguageTag(Locale locale) {
        return locale.getLanguage()
                + ((hasText(locale.getCountry())) ? "-" + locale.getCountry()
                : "");
    }

    public static String[] addStringToArray(String[] array, String str) {
        if (ObjectUtils.isEmpty(array)) {
            return new String[]{str};
        }
        String[] newArr = new String[array.length + 1];
        System.arraycopy(array, 0, newArr, 0, array.length);
        newArr[array.length] = str;
        return newArr;
    }

    public static String[] concatenateStringArrays(String[] array1,
                                                   String[] array2) {
        if (ObjectUtils.isEmpty(array1)) {
            return array2;
        }
        if (ObjectUtils.isEmpty(array2)) {
            return array1;
        }
        String[] newArr = new String[array1.length + array2.length];
        System.arraycopy(array1, 0, newArr, 0, array1.length);
        System.arraycopy(array2, 0, newArr, array1.length, array2.length);
        return newArr;
    }

    public static String[] mergeStringArrays(String[] array1, String[] array2) {
        if (ObjectUtils.isEmpty(array1)) {
            return array2;
        }
        if (ObjectUtils.isEmpty(array2)) {
            return array1;
        }
        List result = new ArrayList();
        result.addAll(Arrays.asList(array1));
        for (int i = 0; i < array2.length; ++i) {
            String str = array2[i];
            if (!(result.contains(str))) {
                result.add(str);
            }
        }
        return toStringArray(result);
    }

    public static String[] sortStringArray(String[] array) {
        if (ObjectUtils.isEmpty(array)) {
            return new String[0];
        }
        Arrays.sort(array);
        return array;
    }

    public static String[] toStringArray(Collection collection) {
        if (collection == null) {
            return null;
        }
        return ((String[]) collection.toArray(new String[collection
                .size()]));
    }

    public static String[] toStringArray(Enumeration enumeration) {
        if (enumeration == null) {
            return null;
        }
        List list = Collections.list(enumeration);
        return ((String[]) list.toArray(new String[list.size()]));
    }

    public static String[] trimArrayElements(String[] array) {
        if (ObjectUtils.isEmpty(array)) {
            return new String[0];
        }
        String[] result = new String[array.length];
        for (int i = 0; i < array.length; ++i) {
            String element = array[i];
            result[i] = ((element != null) ? element.trim() : null);
        }
        return result;
    }

    public static String[] removeDuplicateStrings(String[] array) {
        if (ObjectUtils.isEmpty(array)) {
            return array;
        }
        Set set = new TreeSet();
        for (int i = 0; i < array.length; ++i) {
            set.add(array[i]);
        }
        return toStringArray(set);
    }

    public static String[] split(String toSplit, String delimiter) {
        if ((!(hasLength(toSplit))) || (!(hasLength(delimiter)))) {
            return null;
        }
        int offset = toSplit.indexOf(delimiter);
        if (offset < 0) {
            return null;
        }
        String beforeDelimiter = toSplit.substring(0, offset);
        String afterDelimiter = toSplit.substring(offset + delimiter.length());
        return new String[]{beforeDelimiter, afterDelimiter};
    }

    public static Properties splitArrayElementsIntoProperties(String[] array,
                                                              String delimiter) {
        return splitArrayElementsIntoProperties(array, delimiter, null);
    }

    public static Properties splitArrayElementsIntoProperties(String[] array,
                                                              String delimiter, String charsToDelete) {
        if (ObjectUtils.isEmpty(array)) {
            return null;
        }
        Properties result = new Properties();
        for (int i = 0; i < array.length; ++i) {
            String element = array[i];
            if (charsToDelete != null) {
                element = deleteAny(array[i], charsToDelete);
            }
            String[] splittedElement = split(element, delimiter);
            if (splittedElement == null) {
                continue;
            }
            result.setProperty(splittedElement[0].trim(),
                    splittedElement[1].trim());
        }
        return result;
    }

    public static String[] tokenizeToStringArray(String str, String delimiters) {
        return tokenizeToStringArray(str, delimiters, true, true);
    }

    public static String[] tokenizeToStringArray(String str, String delimiters,
                                                 boolean trimTokens, boolean ignoreEmptyTokens) {
        if (str == null) {
            return null;
        }
        StringTokenizer st = new StringTokenizer(str, delimiters);
        List tokens = new ArrayList();
        while (st.hasMoreTokens()) {
            String token = st.nextToken();
            if (trimTokens) {
                token = token.trim();
            }
            if ((!(ignoreEmptyTokens)) || (token.length() > 0)) {
                tokens.add(token);
            }
        }
        return toStringArray(tokens);
    }

    public static String[] delimitedListToStringArray(String str,
                                                      String delimiter) {
        return delimitedListToStringArray(str, delimiter, null);
    }

    public static String[] delimitedListToStringArray(String str,
                                                      String delimiter, String charsToDelete) {
        if (str == null) {
            return new String[0];
        }
        if (delimiter == null) {
            return new String[]{str};
        }
        List result = new ArrayList();
        if ("".equals(delimiter)) {
            for (int i = 0; i < str.length(); ++i)
                result.add(deleteAny(str.substring(i, i + 1), charsToDelete));
        } else {
            int pos = 0;
            int delPos = 0;
            while ((delPos = str.indexOf(delimiter, pos)) != -1) {
                result.add(deleteAny(str.substring(pos, delPos), charsToDelete));
                pos = delPos + delimiter.length();
            }
            if ((str.length() > 0) && (pos <= str.length())) {
                result.add(deleteAny(str.substring(pos), charsToDelete));
            }
        }
        return toStringArray(result);
    }

    public static String[] commaDelimitedListToStringArray(String str) {
        return delimitedListToStringArray(str, ",");
    }

    public static Set commaDelimitedListToSet(String str) {
        Set set = new TreeSet();
        String[] tokens = commaDelimitedListToStringArray(str);
        for (int i = 0; i < tokens.length; ++i) {
            set.add(tokens[i]);
        }
        return set;
    }

    public static String collectionToDelimitedString(Collection coll,
                                                     String delim, String prefix, String suffix) {
        if (CollectionUtils.isEmpty(coll)) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        Iterator it = coll.iterator();
        while (it.hasNext()) {
            sb.append(prefix).append(it.next()).append(suffix);
            if (it.hasNext())
                ;
            sb.append(delim);
        }

        return sb.toString();
    }

    public static String collectionToDelimitedString(Collection coll,
                                                     String delim) {
        return collectionToDelimitedString(coll, delim, "", "");
    }

    public static String collectionToCommaDelimitedString(Collection coll) {
        return collectionToDelimitedString(coll, ",");
    }

    public static String arrayToDelimitedString(Object[] arr, String delim) {
        if (ObjectUtils.isEmpty(arr)) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < arr.length; ++i) {
            if (i > 0) {
                sb.append(delim);
            }
            sb.append(arr[i]);
        }
        return sb.toString();
    }

    public static String arrayToCommaDelimitedString(Object[] arr) {
        return arrayToDelimitedString(arr, ",");
    }

    public static boolean isEmpty(CharSequence cs) {
        return ((cs == null) || (cs.length() == 0));
    }

    public static boolean isNotEmpty(CharSequence cs) {
        return (!(isEmpty(cs)));
    }

    public static String printStackTraceToString(Throwable t) {
        StringWriter sw = new StringWriter();
        t.printStackTrace(new PrintWriter(sw, true));
        return sw.getBuffer().toString();
    }

}